package cn.dengta.webapp.user.entity;

import java.util.*;
import javax.annotation.Nullable;

import cn.dengta.common.model.*;
import cn.dengta.webapp.base.entity.BizEntity;
import cn.dengta.webapp.user.model.*;
import com.alibaba.fastjson.JSON;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.Accessors;
import me.codeplayer.util.*;

/**
 * 活动表
 *
 * @author lgy
 * @since 2022-08-10
 */
@Setter
@Getter
@Accessors(chain = true)
public class Activity extends BizEntity implements SwitchSupport {

	/** 活动别名 */
	private String alias;
	/** 活动类型 */
	private ActivityType type;
	/** 活动名称 */
	private String name;
	/** 活动缩略图 */
	private String logo;
	/** 活动内容 */
	private String summary;
	/** 活动配置 */
	protected String config;
	/** 额外的配置或备注信息 */
	private String extra;
	/** 活动开始时间 */
	private Date beginTime;
	/** 活动结束时间 */
	private Date endTime;
	/** 性别 */
	private Gender gender;
	/** 客户端 */
	private String client;
	@Nullable
	private Global global;
	/** 站点路径 */
	private String siteUrl;
	private transient ActivityStatusDescriptor statusDescriptor;

	public Activity init(Activity input, Date now) {
		this.type = X.expectNotNull(type, input.type);
		this.name = input.name;
		this.logo = X.expectNotNull(input.logo, logo, "");
		this.summary = X.expectNotNull(input.summary, summary, "");
		this.config = StringUtil.toString(config); // 目前不开放编辑活动配置
		this.extra = X.expectNotNull(input.extra, "");
		this.alias = X.expectNotNull(input.alias, alias);
		this.beginTime = X.expectNotNull(input.beginTime, beginTime);
		this.endTime = X.expectNotNull(input.endTime, endTime);
		super.status = X.expectNotNull(input.status, status, Status.NO.value);
		super.state = X.expectNotNull(input.state, state, State.PUBLIC);
		this.gender = input.gender;
		this.global = input.global;
		this.client = StringUtil.toString(input.client);
		this.siteUrl = X.expectNotNull(input.siteUrl, "");
		super.initTime(now);
		return this;
	}

	public boolean isOpen() {
		return isEnabled();
	}

	@Override
	public boolean isEnabled() {
		return this.status > 0;
	}

	public boolean isActivity(Long baseTime) {
		if (baseTime == null) {
			baseTime = System.currentTimeMillis();
		}
		return isActive(baseTime);
	}

	public long timeDiff(Long baseTime) {
		if (baseTime == null) {
			baseTime = System.currentTimeMillis();
		}
		return Math.max(endTime.getTime() - baseTime, 0L);
	}

	public String descriptorLabel() {
		return getStatusDescriptor(System.currentTimeMillis()).getLabel();
	}

	public Integer descriptorValue() {
		return getStatusDescriptor(System.currentTimeMillis()).getValue();
	}

	public ActivityStatusDescriptor getStatusDescriptor(final long baseTime) {
		ActivityStatusDescriptor descriptor = statusDescriptor;
		if (descriptor == null) {
			if (!isEnabled() || this.endTime.getTime() < baseTime) {
				descriptor = ActivityStatusDescriptor.CLOSE; // 已结束
			} else if (this.beginTime.getTime() > baseTime) {
				descriptor = ActivityStatusDescriptor.WAIT_OPEN; // 即将开始
			} else {
				descriptor = ActivityStatusDescriptor.OPEN; // 进行中
			}
			statusDescriptor = descriptor;
		}
		return descriptor;
	}

	public String statusDesc(final long baseTime) {
		if (this.beginTime.getTime() > baseTime) {
			return "About to start"; // 即将开始
		} else if (this.endTime.getTime() < baseTime) {
			return "over"; // 已结束
		} else {
			return "processing"; // 进行中
		}
	}

	public boolean canDisplay() {
		return isEnabled() && StringUtil.notEmpty(alias);
	}

	public static Map<String, Object> asEmbed(final Activity input) {
		return X.map(input, t -> CollectionUtil.ofHashMap("id", input.getId(), "name", input.getName()));
	}

	/**
	 * 活动配置接口
	 */
	public interface ActivityConfig extends java.io.Serializable {

		/** 表示无效配置的对象实例 */
		ActivityConfig INVALID_CONFIG = new ActivityConfig() {
		};

	}

	/**
	 * 活动类型
	 */
	@Getter
	public enum ActivityType implements ValueProxyImpl<ActivityType, Integer> {
		/** 礼券活动 */
		COUPON(0, "优惠券活动", null, false),
		/** 抽奖活动 */
		LOTTERY(1, "抽奖活动", null, true),
		/** 专题页面 */
		PAGE(2, "专题页面", null, true),
		//
		;
		public Integer value;
		public boolean show;
		public final Class<? extends ActivityConfig> configClass;
		final ValueProxy<ActivityType, Integer> proxy;

		ActivityType(Integer value, String label, Class<? extends ActivityConfig> configClass, boolean show) {
			this.value = value;
			this.configClass = configClass;
			this.show = show;
			this.proxy = new ValueProxy<>(this, value, label);
		}

		public String serialize(ActivityConfig config) {
			return config == null ? "" : JSON.toJSONString(config);
		}

		public ActivityConfig deserialize(String configJSONStr) {
			if (StringUtil.isEmpty(configJSONStr) || configClass == null) {
				return null;
			}
			return JSON.parseObject(configJSONStr, configClass);
		}

		public static final ActivityType[] CACHE = Arrays.stream(values()).filter(ActivityType::isShow).toArray(ActivityType[]::new);

		public static ActivityType[] getValues() {
			return ValueProxy.getCachedArray(ActivityType.class, ActivityType::values);
		}

		public static ActivityType of(Integer value) {
			return COUPON.getValueOf(value);
		}

	}

	@Getter
	public enum ActivityName {
		CARNIVAL("嘉年华", "carnival"),
		LOTTERY2022("转盘抽奖", "lottery2022"),
		PLANET_EXPLORE("星球探险", "planetExplore"),
		HALLOWEEN("万圣节活动", "christmas2022"),
		BIRD202211("小鸟游戏活动", "bird202211"),
		SWEET_PICK("甜蜜pick", "sweetPick"),
		/** 圣诞节活动 */
		CHRISTMAS("圣诞节", "christmas"),
		VALENTINE("情人节", "valentine"),

		GIFT_BAG("男礼包活动", "gift_bag"),
		GIFT_BAG_FEMALE("女礼包活动", "gift_bag_female"),
		/** 四月亲密度活动 */
		APRIL_INTIMACY("四月亲密度活动", "april_intimacy"),

		//
		;
		public final String label;
		public final String alias;

		ActivityName(String label, @Nullable String alias) {
			this.label = label;
			this.alias = alias;
		}

	}

	public static final String ALIAS = "alias";
	public static final String TYPE = "type";
	public static final String NAME = "name";
	public static final String LOGO = "logo";
	public static final String GLOBAL = "global";
	public static final String SUMMARY = "summary";
	public static final String CONFIG = "config";
	public static final String EXTRA = "extra";
	public static final String BEGIN_TIME = "begin_time";
	public static final String END_TIME = "end_time";

}
